import { Room, Client } from "@colyseus/core";
import { IActionMessage, IBooleanMessage, IPlayerJoinedMessage, IXYZMessage, MMO_MESSAGE_TYPE } from '../common';
import { IPlayerInfo, MMOPlayer } from '../mmo-player';
import { RoomState } from '../room-state';


class GameRoom extends Room<RoomState> {

    public onCreate(options: any): void | Promise<any> {
        this.state = new RoomState();
        console.log("GameRoom created!", options);
        this.bindMessage();
    }

    private bindMessage(): void {

        this.onMessage(MMO_MESSAGE_TYPE.PLAYER_POSITION, (client, data: IXYZMessage) => {
            const player = this.state.players.get(client.sessionId);
            if (!player) return;
            player.x = data.x;
            player.y = data.y;
            player.z = data.z;
            this.broadcast(MMO_MESSAGE_TYPE.PLAYER_POSITION, { sessionId: client.sessionId, x: player.x, y: player.y, z: player.z }, { except: client });
        });

        this.onMessage(MMO_MESSAGE_TYPE.PLAYER_ROTATION, (client, data: IXYZMessage) => {
            const player = this.state.players.get(client.sessionId);
            if (!player) return;
            player.rx = data.x;
            player.ry = data.y;
            player.rz = data.z;
            this.broadcast(MMO_MESSAGE_TYPE.PLAYER_ROTATION, { sessionId: client.sessionId, x: player.rx, y: player.ry, z: player.rz }, { except: client });
        });

        this.onMessage(MMO_MESSAGE_TYPE.PLAYER_SCALE, (client, data: IXYZMessage) => {
            const player = this.state.players.get(client.sessionId);
            if (!player) return;
            player.sx = data.x;
            player.sy = data.y;
            player.sz = data.z;
            this.broadcast(MMO_MESSAGE_TYPE.PLAYER_SCALE, { sessionId: client.sessionId, x: player.sx, y: player.sy, z: player.sz }, { except: client });
        });

        this.onMessage(MMO_MESSAGE_TYPE.PLAYER_ACTION, (client, data: IActionMessage) => {
            const player = this.state.players.get(client.sessionId);
            if (!player) return;
            player.actionIndex = data.index;
            player.actionLoop = data.loop;
            this.broadcast(MMO_MESSAGE_TYPE.PLAYER_ACTION, { sessionId: client.sessionId, index: player.actionIndex, loop: player.actionLoop }, { except: client });
        });

        this.onMessage(MMO_MESSAGE_TYPE.PLAYER_VISIBLE, (client, data: IBooleanMessage) => {
            const player = this.state.players.get(client.sessionId);
            if (!player) return;
            player.visible = data.value;
            this.broadcast(MMO_MESSAGE_TYPE.PLAYER_VISIBLE, { sessionId: client.sessionId, value: player.visible }, { except: client });
        });
    }

    public onJoin(client: Client<any, any>, options: IPlayerJoinedMessage, auth?: any): void | Promise<any> {
        console.log("Player joined", client.sessionId, options);
        const player = new MMOPlayer();
        player.id = options.player.id || '';
        player.name = options.player.name || '';
        player.outfit = options.player.outfit || [];
        this.state.players.set(client.sessionId, player);

        this.broadcast(MMO_MESSAGE_TYPE.PLAYER_JOINED, {
            sessionId: client.sessionId,
            player: options.player,
        });

        const players: Array<[string, IPlayerInfo]> = [];
        for (const [key, value] of this.state.players) {
            players.push([key, value.infoObject()]);
        }
        client.send(MMO_MESSAGE_TYPE.ROOM_STATE_PLAYERS, {
            players: players,
        });
    }

    public onLeave(client: Client<any, any>, consented?: boolean): void | Promise<any> {
        const player = this.state.players.get(client.sessionId);
        if (!player) return;
        this.broadcast(MMO_MESSAGE_TYPE.PLAYER_LEFT, {
            sessionId: client.sessionId,
            player: player.infoObject()
        });
        this.state.players.delete(client.sessionId);
    }

    public onDispose(): void | Promise<any> {
        console.log("Room disposed");
    }

}


export {
    GameRoom,
};